package com.haha.http.rpc.server;

import com.haha.http.rpc.common.Request;
import com.haha.http.rpc.common.Response;
import com.haha.http.rpc.common.util.JsonUtils;
import com.haha.http.rpc.common.util.LogUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Map;

/**
 * @author zhangxiaofan07
 * @version 1.0 2022/2/10
 */
@RestController
public class RpcServerWrapperController {
    private static final Logger logger = LoggerFactory.getLogger("RPC-SERVER-DIGEST");

    @Autowired
    private ApplicationContext applicationContext;

    @PostMapping("/rpc")
    public Response handlerRequest(@RequestBody Request request) {
        long startTime = System.currentTimeMillis();

        Class<?> objType = request.getObjType();
        Object bean = applicationContext.getBean(objType);

        String methodName = request.getMethodName();
        Map<Class<?>, Object> paramMap = request.getParamMap();
        if (paramMap == null) {
            paramMap = Collections.EMPTY_MAP;
        }

        Class<?>[] classes = paramMap.keySet().toArray(new Class<?>[0]);
        Response response = null;
        try {
            Method method = objType.getDeclaredMethod(methodName, classes);
            Object data = method.invoke(bean, paramMap.values().toArray());
            response = Response.success(JsonUtils.toJson(data));
            return response;
        } catch (Exception e) {
            LogUtils.error(logger, "rpc server handler request err!", e);
            response = Response.error("SYSTEM_ERR", e.getMessage());
            return response;
        } finally {
            long cost = System.currentTimeMillis() - startTime;
            logger.info("handle rpc request = {}, response = {}, cost = {}ms,",
                    request, response, cost);
        }

    }
}
